using Microsoft.Extensions.Logging;
using SeataNet.Core.Saga;
using SeataNet.Core.TCC;
using SeataNet.Core.Transaction;

namespace SeataNet.Samples
{
    public class InventoryService
    {
        private readonly ITransactionManager _transactionManager;
        private readonly ILogger<InventoryService> _logger;

        public InventoryService(
            ITransactionManager transactionManager,
            ILogger<InventoryService> logger)
        {
            _transactionManager = transactionManager;
            _logger = logger;
        }

        /// <summary>
        /// AT模式检查库存
        /// </summary>
        public async Task<bool> CheckStockAsync(string productId, int quantity)
        {
            _logger.LogInformation($"检查库存，产品ID: {productId}, 数量: {quantity}");
            
            // 模拟从数据库查询库存
            var currentStock = await GetStockAsync(productId);
            var hasEnoughStock = currentStock >= quantity;
            
            _logger.LogInformation($"当前库存: {currentStock}, 需求: {quantity}, 库存充足: {hasEnoughStock}");
            return hasEnoughStock;
        }

        /// <summary>
        /// AT模式扣减库存
        /// </summary>
        [GlobalTransactional(Name = "inventory-deduct-at", Timeout = 30000)]
        public async Task<bool> DeductStockAsync(string productId, int quantity)
        {
            _logger.LogInformation($"开始扣减库存，产品ID: {productId}, 数量: {quantity}");
            
            // 1. 检查库存
            var currentStock = await GetStockAsync(productId);
            if (currentStock < quantity)
            {
                throw new InvalidOperationException($"库存不足，当前库存: {currentStock}, 需求: {quantity}");
            }

            // 2. 扣减库存
            var newStock = currentStock - quantity;
            await UpdateStockAsync(productId, newStock);

            // 3. 记录库存变动
            var recordId = Guid.NewGuid().ToString("N");
            await RecordStockChangeAsync(recordId, productId, quantity, "deduct");

            _logger.LogInformation($"库存扣减成功，产品ID: {productId}, 扣减数量: {quantity}, 剩余库存: {newStock}");
            return true;
        }

        /// <summary>
        /// TCC模式尝试扣减库存
        /// </summary>
        public async Task<bool> TryDeductStockAsync(string productId, int quantity)
        {
            _logger.LogInformation($"TCC Try: 尝试扣减库存，产品ID: {productId}, 数量: {quantity}");
            
            // 1. 检查库存
            var currentStock = await GetStockAsync(productId);
            if (currentStock < quantity)
            {
                return false;
            }

            // 2. 预留库存
            var reserved = await TryReserveStockAsync(productId, quantity);
            if (!reserved)
            {
                return false;
            }

            // 3. 记录预留
            var recordId = Guid.NewGuid().ToString("N");
            var recordReserved = await TryRecordStockChangeAsync(recordId, productId, quantity, "reserve");
            if (!recordReserved)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// Saga模式扣减库存
        /// </summary>
        [GlobalTransactional(Name = "inventory-deduct-saga", Timeout = 60000)]
        public async Task<bool> DeductStockWithSagaAsync(string productId, int quantity)
        {
            _logger.LogInformation($"Saga模式开始扣减库存，产品ID: {productId}, 数量: {quantity}");
            
            // 1. 检查库存
            var currentStock = await GetStockAsync(productId);
            if (currentStock < quantity)
            {
                throw new InvalidOperationException($"库存不足，当前库存: {currentStock}, 需求: {quantity}");
            }

            // 2. 扣减库存
            var newStock = currentStock - quantity;
            await UpdateStockAsync(productId, newStock);

            // 3. 记录库存变动
            var recordId = Guid.NewGuid().ToString("N");
            await RecordStockChangeAsync(recordId, productId, quantity, "deduct");

            _logger.LogInformation($"Saga模式库存扣减成功，产品ID: {productId}, 扣减数量: {quantity}, 剩余库存: {newStock}");
            return true;
        }

        /// <summary>
        /// XA模式扣减库存
        /// </summary>
        [GlobalTransactional(Name = "inventory-deduct-xa", Timeout = 30000)]
        public async Task<bool> DeductStockXaAsync(string productId, int quantity)
        {
            _logger.LogInformation($"XA模式开始扣减库存，产品ID: {productId}, 数量: {quantity}");
            
            // 1. 检查库存
            var currentStock = await GetStockAsync(productId);
            if (currentStock < quantity)
            {
                throw new InvalidOperationException($"库存不足，当前库存: {currentStock}, 需求: {quantity}");
            }

            // 2. 扣减库存
            var newStock = currentStock - quantity;
            await UpdateStockXaAsync(productId, newStock);

            // 3. 记录库存变动
            var recordId = Guid.NewGuid().ToString("N");
            await RecordStockChangeXaAsync(recordId, productId, quantity, "deduct");

            _logger.LogInformation($"XA模式库存扣减成功，产品ID: {productId}, 扣减数量: {quantity}, 剩余库存: {newStock}");
            return true;
        }

        private async Task<int> GetStockAsync(string productId)
        {
            // 模拟从数据库查询库存
            _logger.LogInformation($"查询产品库存: {productId}");
            await Task.Delay(30); // 模拟数据库操作
            
            // 模拟返回库存数量
            return 1000; // 假设库存充足
        }

        private async Task<bool> TryReserveStockAsync(string productId, int quantity)
        {
            // 模拟TCC模式的Try阶段预留库存
            _logger.LogInformation($"TCC Try: 预留产品库存: {productId}, 数量: {quantity}");
            await Task.Delay(30); // 模拟数据库操作
            return true; // 假设总是成功
        }

        private async Task UpdateStockAsync(string productId, int newStock)
        {
            // 模拟更新库存到数据库
            _logger.LogInformation($"更新产品库存: {productId}, 新库存: {newStock}");
            await Task.Delay(30); // 模拟数据库操作
        }

        private async Task UpdateStockXaAsync(string productId, int newStock)
        {
            // 模拟XA模式更新库存到数据库
            _logger.LogInformation($"XA更新产品库存: {productId}, 新库存: {newStock}");
            await Task.Delay(30); // 模拟数据库操作
        }

        private async Task RecordStockChangeAsync(string recordId, string productId, int quantity, string operation)
        {
            // 模拟记录库存变动到数据库
            _logger.LogInformation($"记录库存变动: {recordId}, 产品ID: {productId}, 数量: {quantity}, 操作: {operation}");
            await Task.Delay(20); // 模拟数据库操作
        }

        private async Task<bool> TryRecordStockChangeAsync(string recordId, string productId, int quantity, string operation)
        {
            // 模拟TCC模式的Try阶段记录库存变动
            _logger.LogInformation($"TCC Try: 预留库存变动记录: {recordId}, 产品ID: {productId}, 数量: {quantity}, 操作: {operation}");
            await Task.Delay(20); // 模拟数据库操作
            return true; // 假设总是成功
        }

        private async Task RecordStockChangeXaAsync(string recordId, string productId, int quantity, string operation)
        {
            // 模拟XA模式记录库存变动到数据库
            _logger.LogInformation($"XA记录库存变动: {recordId}, 产品ID: {productId}, 数量: {quantity}, 操作: {operation}");
            await Task.Delay(20); // 模拟数据库操作
        }

        // TCC模式的Confirm方法
        [GlobalTransactionalConfirm]
        public async Task ConfirmDeductStockAsync(string productId, int quantity)
        {
            _logger.LogInformation($"TCC Confirm: 确认扣减库存: {productId}, 数量: {quantity}");
            await Task.Delay(20); // 模拟数据库操作
        }

        // TCC模式的Cancel方法
        [GlobalTransactionalCancel]
        public async Task CancelDeductStockAsync(string productId, int quantity)
        {
            _logger.LogInformation($"TCC Cancel: 取消扣减库存: {productId}, 数量: {quantity}");
            await Task.Delay(20); // 模拟数据库操作
        }

        // Saga模式的补偿方法
        [GlobalTransactionalCompensation]
        public async Task CompensateDeductStockAsync(string productId, int quantity)
        {
            _logger.LogInformation($"Saga Compensate: 补偿扣减库存: {productId}, 数量: {quantity}");
            await Task.Delay(20); // 模拟数据库操作
        }
    }
}